Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugin): support command's flags #3060

Merged
merged 50 commits into from
Nov 15, 2022
Merged

feat(plugin): support command's flags #3060

merged 50 commits into from
Nov 15, 2022

Conversation

tbruyelle
Copy link
Contributor

@tbruyelle tbruyelle commented Nov 4, 2022

This change brings support to command's flags by :

  • Adding a Flags fields to plugin.Command struct.
    This allows the user to add flags to his plugin's command.
  • Expose a Flags() *pflag.Flagset function inside Execute* plugin method argument.
    So the user can retrieve flags values like he used to do with cobra.
  • Make pflag.Flag serializable.
    This is required because the plugin and the ignite binary communicate via the network. Since pflag.Flag has a lot of un-exported fields, serialization doesn't work out the box for this type. I had a create a subsidiary type for that.

Other changes:

  • Merge Commands() and Hooks() methods into a single Manifest method.
    This simplifiy the declaration of what the plugin is doing via an unique method.
  • Revamp plugin main.go to illustrate the flag support, and add a getChain function to retrieve the chain data.
    As a result, there's no longer the need for exporting newChainWithHomeFlags().
  • Update xgit.InitAndCommit() so it doesn't create a git repo if the path parameter is already inside a git repo.
    This is useful for plugins when a repo is aimed to contain multiple plugins, we don't want the plugin scaffold command to create a subsidiary git repo inside the main git repo. This doesn't impact the scaffold chain command, unless it's invoked inside an existing git repo.
  • Change Execute* methods signature so they take a single ExecutedCommand or ExecutedHook argument.
    This avoids mixing definition type Command and Hook and runtime type ExecutedCommand and ExecutedHook.
  • Improve error handling when the plugin returns an error.
  • test: replace custom plugin.Interface with a one generated by mockery.
  • test: update scaffolded plugin go.mod so it uses the cloned cli repo via a replace directive.
    Before that change, the tests weren't using the current cli but the cli declared in the plugin go.mod.plush.

aljo242
aljo242 previously approved these changes Nov 4, 2022
aljo242
aljo242 previously approved these changes Nov 4, 2022
@tbruyelle tbruyelle marked this pull request as draft November 4, 2022 16:28
@tbruyelle
Copy link
Contributor Author

Converted to draft because I want to wait for #3038 to be merged, and then add flags support to hooks.

@tbruyelle
Copy link
Contributor Author

@aljo242 it's ready now, sorry there's more changes than expected...

ignite/cmd/plugin.go Show resolved Hide resolved
ignite/cmd/plugin.go Show resolved Hide resolved
ignite/services/plugin/interface.go Show resolved Hide resolved
ignite/pkg/cosmostxcollector/mocks/saver.go Outdated Show resolved Hide resolved
@joshLong145
Copy link
Contributor

Observing that when a hook is invoked with ExecutedHook as the parameter the Command is properly hydrated but the Hook is always an empty struct. you can reproduce this with the example I have here: https://github.com/joshLong145/plugin-example. It's a strange bug as I would expect both to be empty definitions.

Comment on lines +21 to 23
// InitAndCommit creates a git repo in path if path isn't already inside a git
// repository, then commits path content.
func InitAndCommit(path string) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we can test this function?

Would just be tracked in a new issue. Not part of this scope.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure it's possible, I've already created git repositories on the fly during the load plugin tests.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we create an issue for testing this in the future?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, done there #3125

@tbruyelle
Copy link
Contributor Author

Observing that when a hook is invoked with ExecutedHook as the parameter the Command is properly hydrated but the Hook is always an empty struct. you can reproduce this with the example I have here: https://github.com/joshLong145/plugin-example. It's a strange bug as I would expect both to be empty definitions.

Indeed I can reproduce the problem, I didn't noticed it during my tests. Will try to find why, if you have any idea, tell me :)

ExecuteCommand cannot implement gob decoder/encoder and at the same time
being embeded in ExecutedHook.
@tbruyelle
Copy link
Contributor Author

tbruyelle commented Nov 10, 2022

@joshLong145 fixed 869bf71

The issue was because ExecutedCommand implements gob decoder/encoder and at the same time is embeded in ExecutedHook. In this particular situation it seems like gob takes the return of ExecuteCommand.GobDecode and put in ExecutedHook, without other kind of verification.

Thanks for spotting it!

@joshLong145
Copy link
Contributor

Observing that when a hook is invoked with ExecutedHook as the parameter the Command is properly hydrated but the Hook is always an empty struct. you can reproduce this with the example I have here: https://github.com/joshLong145/plugin-example. It's a strange bug as I would expect both to be empty definitions.

Indeed I can reproduce the problem, I didn't noticed it during my tests. Will try to find why, if you have any idea, tell me :)

trying to narrow it down myself. focusing on the creation of the struct during loadPluginHooks wondering if it has to do

@joshLong145 fixed 869bf71

The issue was because ExecutedCommand implements gob decoder/encoder and at the same time is embeded in ExecutedHook. In this particular situation it seems like gob takes the return of ExecuteCommand.GobDecode and put in ExecutedHook, without other kind of verification.

Thanks for spotting it!

that's interesting would not have thought it would work that way. I tested again it now is hydrating properly. 👍

@aljo242 aljo242 changed the base branch from develop to main November 15, 2022 13:52
@aljo242 aljo242 merged commit 184caaa into main Nov 15, 2022
@aljo242 aljo242 deleted the feat/plugin-cmd-flags branch November 15, 2022 21:10
Jchicode pushed a commit to Jchicode/cli that referenced this pull request Aug 9, 2023
* wip

* wip: implements gob decoder/encoder

* flags data are passing the network

* hide flags field and expose Flags() func like cobra.Command

* Remove cobra.Command field from plugin.Command

The field was passed to give access to the flags, but that wasb;t
working because cobra.Command is not fully serializable (it has a lot of
unexported fields).

* comments

* add int64 flag type

* test: add flags

* test: plugin use current ignite/cli

* chore: upgrade plugin CLI dep

* fix: InitAndCommit doesn't create repo if already exists

* chore: improve plugin default code

* add CL entry

* chore: update plugin CLI dep

* fix after merge

* dont remove band now

* remove replace in plugin gomod and use latest version

* fix: plugin.Hooks can return an error

* update plugin dep version

* add spinner during plugin scaffolding

* fix: populate hook.with with plugin config

* test: execute commands on linkPluginCmds

* test: assert args in TestLinkPluginCmds

* test: global args in TestLinkPluginHooks

* refac(plugin): merge Commands and Hooks into Manifest

Also stop using the same type for definition and execution. Now Manifest
returns definition with type Command and Hook, while Execute* methods
takes ExecutedCommand and ExecutedHook as parameters.

* fix lint error

* improve plugin error handling

* feat(plugin): support more flag types

* update plugin cli version and other fixes

* test: try to fix

* docs: comment

* docs: more comments

* docs: more comments

* docs: comments

* remove slack private lnk

* remove private slack link

* run make format

* docs: add code comments

* fix: ExecuteCommand embedding

ExecuteCommand cannot implement gob decoder/encoder and at the same time
being embeded in ExecutedHook.

Co-authored-by: Alex Johnson <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants